#include "InetAddr.hpp"
#include "Log.hpp"
#include <sys/epoll.h>
#include <memory>
#include "Socket.hpp"

#define MAX_NUMS 1024
class EpollServer
{
    const static int default_fd = -1;
    const static int default_nums = 4096;
    void HandlerIO(int fd)
    {
        char buffer[default_nums];
        ssize_t n = recv(fd, buffer, sizeof(buffer) - 1, 0);
        if (n == 0)
        {
            LOG(DEBUG, "读端关闭，即将移除监控!\n");
            epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, nullptr);
            close(fd);
        }
        else if (n == -1)
        {
            LOG(ERROR, "recv failed!\n");
            epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, nullptr);
            close(fd);
        }
        else
        {
            buffer[n] = 0;
            std::cout << "client say# " << buffer << std::endl;

            std::string response = "HTTP/1.0 200 ok\r\n";
            std::string content = "<html><body><h1>hello bite, hello world</h1></body></html>";
            response += "Content-Type: text/html\r\n";
            response += "Content-Length: " + std::to_string(content.size()) + "\r\n";
            response += "\r\n";
            response += content;
            ::send(fd, response.c_str(), response.size(), 0);
        }
    }

    void Handle_Connection()
    {
        InetAddr addr;
        int sockfd = _listensock->Accepter(&addr);
        struct epoll_event ev;
        ev.data.fd = sockfd;
        ev.events = EPOLLIN;
        ev.events |= EPOLLET;
        int n = ::epoll_ctl(_epfd, EPOLL_CTL_ADD, sockfd, &ev);
        if (n < 0)
        {
            perror("xxx");
            LOG(ERROR, "epoll add failed!\n");
            return;
        }
    }

    void HandlerEvent(int n)
    {
        for (int i = 0; i < n; i++)
        {
            if (_revent[i].data.fd == _listensock->Sockfd())
                Handle_Connection();
            else
            {
                if (_revent[i].events & EPOLLIN)
                    HandlerIO(_revent[i].data.fd);
                else if (_revent[i].events & EPOLLOUT)
                    ;
                else
                    LOG(DEBUG, "xxxxxxxxxxx\n");
            }
        }
    }

public:
    EpollServer(uint16_t port, int nums = MAX_NUMS) : _port(port),
                                                      _nums(nums),
                                                      _isrunning(false),
                                                      _epfd(default_fd),
                                                      _listensock(std::make_unique<TcpSocket>())
    {
        _listensock->BuildListenSocket(_port);
    }

    void Init()
    {
        _epfd = ::epoll_create(MAX_NUMS+1);
        if (_epfd < 0)
        {
            LOG(ERROR, "epoll create failed!\n");
            exit(2);
        }
        struct epoll_event ev;
        ev.data.fd = _listensock->Sockfd();
        ev.events = EPOLLIN;
        ev.events |= EPOLLET;
        int ret = ::epoll_ctl(_epfd, EPOLL_CTL_ADD, _listensock->Sockfd(), &ev);
        if (ret < 0)
        {
            LOG(ERROR, "事件添加失败\n");
            exit(3);
        }
    }

    void Loop()
    {
        _isrunning = true;
        while (_isrunning)
        {

            int timeout = 1000;
            int n = ::epoll_wait(_epfd, _revent, _nums, -1);
            if (n < 0)
            {
                LOG(ERROR, "epoll wait error!\n");
                continue;
            }
            else if (n == 0)
            {
                LOG(DEBUG, "wait 超时 %d\n", timeout);
                continue;
            }
            else
            {
                HandlerEvent(n);
            }
        }
    }

private:
    bool _isrunning;
    uint16_t _port;
    int _nums;
    int _epfd;
    std::unique_ptr<Socket> _listensock;
    struct epoll_event _revent[MAX_NUMS];
};